/*
* Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler
* Copyright (C) 2007 Reto Schuettel, Robin Stocker
*
* IFS Institute for Software, HSR Rapperswil, Switzerland
*
*/
package org.python.pydev.refactoring.codegenerator.constructorfield.edit;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.python.pydev.core.MisconfigurationException;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assign;
import org.python.pydev.parser.jython.ast.Attribute;
import org.python.pydev.parser.jython.ast.Call;
import org.python.pydev.parser.jython.ast.Expr;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.jython.ast.NameTokType;
import org.python.pydev.parser.jython.ast.argumentsType;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.jython.ast.stmtType;
import org.python.pydev.parser.jython.ast.factory.NodeHelper;
import org.python.pydev.refactoring.ast.adapters.FunctionDefAdapter;
import org.python.pydev.refactoring.ast.adapters.IClassDefAdapter;
import org.python.pydev.refactoring.ast.adapters.INodeAdapter;
import org.python.pydev.refactoring.codegenerator.constructorfield.request.ConstructorFieldRequest;
import org.python.pydev.refactoring.core.edit.AbstractInsertEdit;
public class ConstructorMethodEdit extends AbstractInsertEdit {
private static final String KWARGS = "kwargs";
private static final String ARGS = "args";
private int offsetStrategy;
private List<INodeAdapter> attributes;
private IClassDefAdapter classAdapter;
public ConstructorMethodEdit(ConstructorFieldRequest req) {
super(req);
this.classAdapter = req.classAdapter;
this.attributes = req.attributeAdapters;
this.offsetStrategy = req.offsetStrategy;
}
/**
* Tricky :)
* @throws MisconfigurationException
*/
@Override
protected SimpleNode getEditNode() throws MisconfigurationException {
List<IClassDefAdapter> bases = classAdapter.getBaseClasses();
//extractArguments
NameTokType varArg = null;
NameTokType kwArg = null;
Set<String> argsNames = new LinkedHashSet<String>();
for (IClassDefAdapter baseClass : bases) {
FunctionDefAdapter init = baseClass.getFirstInit();
if (init != null) {
if (!init.getArguments().hasOnlySelf()) {
argsNames.addAll(init.getArguments().getSelfFilteredArgNames());
}
if (varArg == null && init.getArguments().hasVarArg()) {
varArg = new NameTok(ARGS, NameTok.VarArg);
}
if (kwArg == null && init.getArguments().hasKwArg()) {
kwArg = new NameTok(KWARGS, NameTok.KwArg);
}
}
}
//addOwnArguments
for (INodeAdapter adapter1 : attributes) {
argsNames.add(nodeHelper.getPublicAttr(adapter1.getName()));
}
List<exprType> argsExprList = new ArrayList<exprType>();
Name selfArg = new Name(NodeHelper.KEYWORD_SELF, Name.Param, false);
argsExprList.add(selfArg);
for (String parameter : argsNames) {
argsExprList.add(new Name(parameter.trim(), Name.Param, false));
}
exprType[] argsExpr = argsExprList.toArray(new exprType[0]);
argumentsType args = new argumentsType(argsExpr, varArg, kwArg, null, null, null, null, null, null, null);
//constructorCalls
List<stmtType> body = new ArrayList<stmtType>();
for (IClassDefAdapter base : bases) {
Expr init = extractConstructorInit(base);
if (init != null) {
body.add(init);
}
}
//initAttributes
for (INodeAdapter adapter : attributes) {
exprType target = new Attribute(new Name(NodeHelper.KEYWORD_SELF, Name.Load, false), new NameTok(
adapter.getName(), NameTok.Attrib), Attribute.Store);
Assign initParam1 = new Assign(new exprType[] { target }, new Name(nodeHelper.getPublicAttr(adapter
.getName()), Name.Load, false));
Assign initParam = initParam1;
body.add(initParam);
}
//create function def
return new FunctionDef(new NameTok(NodeHelper.KEYWORD_INIT, NameTok.FunctionName), args,
body.toArray(new stmtType[0]), null, null);
}
private Expr extractConstructorInit(IClassDefAdapter base) {
FunctionDefAdapter init = base.getFirstInit();
if (init != null) {
if (!init.getArguments().hasOnlySelf()) {
Attribute classInit = new Attribute(new Name(moduleAdapter.getBaseContextName(this.classAdapter,
base.getName()), Name.Load, false), new NameTok(NodeHelper.KEYWORD_INIT, NameTok.Attrib),
Attribute.Load);
List<exprType> constructorParameters = init.getArguments().getSelfFilteredArgs();
Name selfArg = new Name(NodeHelper.KEYWORD_SELF, Name.Load, false);
constructorParameters.add(0, selfArg);
exprType[] argExp = constructorParameters.toArray(new exprType[0]);
Name varArg = null;
Name kwArg = null;
if (init.getArguments().hasVarArg()) {
varArg = new Name(ARGS, Name.Load, false);
}
if (init.getArguments().hasKwArg()) {
kwArg = new Name(KWARGS, Name.Load, false);
}
Call initCall = new Call(classInit, argExp, null, varArg, kwArg);
return new Expr(initCall);
}
}
return null;
}
@Override
public int getOffsetStrategy() {
return offsetStrategy;
}
}